package patterns;

public class ComputerBuilderTest {
    
    public static void main(String[] args) {
        Computer computer = new ComputerBuilder().memory(5).disk(2).cpu("aser").build();
        System.out.println(computer);
    }
}

class ComputerBuilder implements $CMD {

    public $MD cpu(final String cpu) {
        return new $MD() {
            public $D memory(final long memory) {
                return new $D() {
                    public $ disk(final long disk) {
                        return new $() {
                            public Computer build() {
                                return new Computer(cpu, memory, disk);
                            }
                        };
                    }
                };
            }
            
            public $M disk(final long disk) {
                return new $M() {
                    public $ memory(final long memory) {
                        return new $() {
                            public Computer build() {
                                return new Computer(cpu, memory, disk);
                            }
                        };
                    }
                };
            }
        };
    }
    
    public $DC memory(final long memory) {
        return new $DC() {
            public $C disk(final long disk) {
                return new $C() {
                    public $ cpu(final String cpu) {
                        return new $() {
                            public Computer build() {
                                return new Computer(cpu, memory, disk);
                            }
                        };
                    }
                };
            }
            
            public $D cpu(final String cpu) {
                return new $D() {
                    public $ disk(final long disk) {
                        return new $() {
                            public Computer build() {
                                return new Computer(cpu, memory, disk);
                            }
                        };
                    }
                };
            }
        };
    }
    
    public $CM disk(final long disk) {
        return new $CM() {
            public $M cpu(final String cpu) {
                return new $M() {
                    public $ memory(final long memory) {
                        return new $() {
                            public Computer build() {
                                return new Computer(cpu, memory, disk);
                            }
                        };
                    }
                };
            }
            
            public $C memory(final long memory) {
                return new $C() {
                    public $ cpu(final String cpu) {
                        return new $() {
                            @Override
                            public Computer build() {
                                return new Computer(cpu, memory, disk);
                            }
                        };
                    }
                };
            }
        };
    }
}

interface $CMD {

    public $MD cpu(String cpu);

    public $DC memory(long memory);

    public $CM disk(long disk);
}

interface $CM {

    $M cpu(String cpu);

    $C memory(long memory);
}

interface $MD {

    $D memory(long memory);

    $M disk(long disk);
}

interface $DC {

    $C disk(long disk);

    $D cpu(String cpu);
}

interface $C {

    $ cpu(String cpu);
}

interface $M {

    $ memory(long memory);
}

interface $D {

    $ disk(long disk);
}

interface $ {

    Computer build();
}

class Computer {

    private String cpu;
    private long memory;
    private long disk;
    
    Computer(String cpu, long memory, long disk) {
        this.cpu = cpu;
        this.memory = memory;
        this.disk = disk;
    }
    
    @Override
    public String toString() {
        return "Computer["
                + "cpu=" + cpu
                + ", memory=" + memory
                + ", disk=" + disk
                + ']';
    }
}
